#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
IR 表达式基础类定义
"""

import ast
from dataclasses import dataclass, field
from typing import Optional, Iterator
from ..base import IRNode


@dataclass
class IRExpr(IRNode):
    """表达式基类"""

    node_type: str = "expr"


@dataclass
class IRRawExpr(IRExpr):
    """原始表达式节点，直接包含代码字符串"""

    code: str = field(default="")
    raw_node: Optional[ast.AST] = field(default=None)  # 保存原始 AST 节点
    node_type: str = "raw_expr"

    def build_from_ast(self, node: ast.AST) -> None:
        """从 AST 节点构建原始表达式内容

        Args:
            node: AST 节点
        """
        super().build_from_ast(node)

        self.code = ast.unparse(node)
        self.raw_node = node  # 保存原始节点以便后续处理（如切片）


def build_expr_from_ast(node: ast.AST, parent: Optional["IRNode"] = None) -> "IRNode":
    """从 AST 节点构建表达式 IR 节点的统一函数

    Args:
        node: AST 节点
        parent: 父节点，如果提供则自动设置为构建节点的父节点

    Returns:
        对应的 IR 表达式节点
    """
    if isinstance(node, ast.Constant):
        from .basic import IRConstant

        expr = IRConstant(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Name):
        from .basic import IRName

        expr = IRName(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Attribute):
        from .access import IRAttribute

        expr = IRAttribute(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Call):
        from .call import IRCall

        expr = IRCall(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.UnaryOp):
        from .operators import IRUnaryOp

        expr = IRUnaryOp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.BinOp):
        from .operators import IRBinOp

        expr = IRBinOp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Subscript):
        from .access import IRSubscript

        expr = IRSubscript(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Slice):
        from .access import IRSlice

        expr = IRSlice(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Compare):
        from .operators import IRCompare

        expr = IRCompare(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.BoolOp):
        from .operators import IRBoolOp

        expr = IRBoolOp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.IfExp):
        from .control import IRConditional

        expr = IRConditional(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.JoinedStr):
        from .string import IRSFormat

        expr = IRSFormat(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Dict):
        from .literals import IRDict

        expr = IRDict(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.List):
        from .literals import IRList

        expr = IRList(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Tuple):
        from .literals import IRTuple

        expr = IRTuple(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Set):
        from .literals import IRSet

        expr = IRSet(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.GeneratorExp):
        from .comprehension import IRGeneratorExp

        expr = IRGeneratorExp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.ListComp):
        from .comprehension import IRListComp

        expr = IRListComp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.SetComp):
        from .comprehension import IRSetComp

        expr = IRSetComp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.DictComp):
        from .comprehension import IRDictComp

        expr = IRDictComp(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Lambda):
        from .lambda_expr import IRLambda

        expr = IRLambda(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, ast.Await):
        from .await_expr import IRAwait

        expr = IRAwait(parent=parent)
        expr.build_from_ast(node)
    elif isinstance(node, (ast.Import, ast.ImportFrom)):
        from ..declarations import IRImportNode

        expr = IRImportNode(parent=parent)
        expr.build_from_ast(node)
    else:
        # 对于不支持的节点类型，使用原始表达式
        expr = IRRawExpr(parent=parent)
        expr.build_from_ast(node)

    return expr
